// immutable.cpp


#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <ctime>

#include <chrono>
#include <mutex>
#include <string>
#include <thread>


namespace blogs
{


using std::chrono::milliseconds;
using std::string;


class Person
{

  private:

    string
    __name__;


    string
    __address__;


  public:

    Person(string name, string address)
        : __name__(name), __address__(address)
    {
    }


    string
    get_name() const
    {
        return __name__;
    }


    string
    get_address() const
    {
        return __address__;
    }


    string
    to_string() const
    {
        string s;
        s += "[ Person: ";
        s += ("name = " + __name__);
        s += ", ";
        s += ("address = " + __address__);
        s += " ]";
        return s;
    }

};


class Printer
{

  private:

    string
    __name__;


    Person const&
    __person__;


  public:

    Printer(string name, Person const& person)
        : __name__(name), __person__(person)
    {
    }


    void
    run()
    {
        while (true) {
            std::printf("%s prints %s.\n", __name__.c_str(), __person__.to_string().c_str());
            std::this_thread::sleep_for(milliseconds(std::rand()%1000));
        }
    }

};


void
bye(int sig = SIGTERM)
{
    std::printf("\nBye Immutable...\n\n");
    std::exit(sig);
}


} // end of namespace blogs


int
main(int argc, char * argv[])
{
    using std::thread;
    using blogs::Person;
    using blogs::Printer;

    std::signal(SIGINT, blogs::bye);
    std::srand(std::time(0));

    Person alice("Alice", "Alaska");
    Printer p1("Printer1", alice);
    Printer p2("Printer2", alice);
    Printer p3("Printer3", alice);

    thread t1(&Printer::run, &p1);
    thread t2(&Printer::run, &p2);
    thread t3(&Printer::run, &p3);

    t1.join();
    t2.join();
    t3.join();

    blogs::bye();
    return 0;
}

